//
// Created by wujehy on 2020/5/29.
//

#include "KeyValueBase.h"

#include <fstream>
#ifdef FILE_PERSISTENNCE_ENABLE
#include "KeyValueDataTypeSerialize.pb.h"
#endif
using namespace GeeJoan::DataBase;

KeyValueDataTypePort KeyValueBase::Get(std::string &key)
{
    auto find = cacheKeyValueMap.find( key );
    if (find == cacheKeyValueMap.end())
    {
        return nullptr;
    } else
    {
        return find->second;
    }
}

KeyValueBase::~KeyValueBase()
{

    for (auto v : cacheKeyValueMap)
    {
        v.second.reset();
    }
    cacheKeyValueMap.clear();

}

KeyValueDataTypePort KeyValueBase::Get2(std::string key)
{
    return Get( key );

}

void KeyValueBase::setUserKey(std::string key, void *port, UserPortDeleteFunction deleteFunction)
{
    auto find = cacheKeyValueMap.find( key );
    // 已存在 删除 旧的 插入新的
    if (find != cacheKeyValueMap.end())
    {
        cacheKeyValueMap.erase( find );
    }
    cacheKeyValueMap[key] = std::shared_ptr<KeyValueDataType>( new KeyValueDataType( port, deleteFunction ));
}

void KeyValueBase::ForEcho(ForEchoCallbackFunction callbackFunction)
{
    for (auto v : cacheKeyValueMap)
    {
        callbackFunction( v.first, v.second );
    }
}


void KeyValueFileService::setMFileName(const std::string &mFileName)
{
    m_filename = mFileName;
}

void KeyValueFileService::setMSecretKey(const std::string &mSecretKey)
{
    m_secret_key = mSecretKey;
}
#ifdef FILE_PERSISTENNCE_ENABLE
///**
// * @brief
// * @tparam SType 序列化的类型
// * @tparam VDType ValueData类型
// * @tparam MV 缓存map 里的值
// * @tparam SEnum 序列化的枚举类型
// * @param[in] v map的Value
// * @param[in] serialStringList map
// * @param[in] se 序列化的枚举
// * @return 插入成功失败
// */
//template<class SType,class VDType, typename SEnum>
//bool MapInserToSerialize(std::string &key, ValueDataBaseTypePort v, SerialStringList &serialStringList,SEnum se)
//{
//    SType serialize;
//    VDType *valueData = (VDType *) v.get();
//    serialize.set_data( valueData->data );
//    // 中间类型
//    SerialByteDataType serialByteDataType;
//    serialByteDataType.set_value_type( se);
//    serialByteDataType.set_data( serialize.SerializeAsString());
//    // 插入
//    serialStringList.mutable_datas()->insert(
//            google::protobuf::MapPair<std::string, SerialByteDataType>( key, serialByteDataType ));
//}

void KeyValueFileService::save()
{
    // 序列化
    SerialStringList serialStringList;

    serialStringList.set_name( m_filename );

    // 序列化
    for (auto v : cacheKeyValueMap)
    {
        std::string tempStr;
        switch (v.second->getType())
        {
            // Int64 部分的序列化
            case ValueType_INT64:
            {
                // 序列化
                // 原数据
                SerializeInt64 serialize;
                ValueDataInt64Type *valueData = (ValueDataInt64Type *) v.second->getDataPort().get();
                serialize.set_data( valueData->data );
                // 中间类型
                SerialByteDataType serialByteDataType;
                serialByteDataType.set_value_type( SerializeValueType::INT64_TYPE );
                serialByteDataType.set_data( serialize.SerializeAsString());
                // 插入
                serialStringList.mutable_datas()->insert(
                        google::protobuf::MapPair<std::string, SerialByteDataType>( v.first, serialByteDataType ));

                break;
            }
            // int32
            case ValueType_UInt8:
            case ValueType_INT32:
            {
                // 序列化
                // 原数据
                SerializeInt32 serialize;
                ValueDataInt32Type *valueData = (ValueDataInt32Type *) v.second->getDataPort().get();
                serialize.set_data( valueData->data );
                // 中间类型
                SerialByteDataType serialByteDataType;
                serialByteDataType.set_value_type( SerializeValueType::INT32_TYPE );
                serialByteDataType.set_data( serialize.SerializeAsString());
                // 插入
                serialStringList.mutable_datas()->insert(
                        google::protobuf::MapPair<std::string, SerialByteDataType>( v.first, serialByteDataType ));

                break;
            }

                // float
            case ValueType_FLOAT:
            {
                // 序列化
                // 原数据
                SerializeFloat serialize;
                ValueDataFloatType *valueData = (ValueDataFloatType *) v.second->getDataPort().get();
                serialize.set_data( valueData->data );
                // 中间类型
                SerialByteDataType serialByteDataType;
                serialByteDataType.set_value_type( SerializeValueType::Float_TYPE );
                serialByteDataType.set_data( serialize.SerializeAsString());
                // 插入
                serialStringList.mutable_datas()->insert(
                        google::protobuf::MapPair<std::string, SerialByteDataType>( v.first, serialByteDataType ));

                break;
            }

                // double
            case ValueType_DOUBLE:
            {
                // 序列化
                // 原数据
                SerializeDouble serialize;
                ValueDataDoubleType *valueData = (ValueDataDoubleType *) v.second->getDataPort().get();
                serialize.set_data( valueData->data );
                // 中间类型
                SerialByteDataType serialByteDataType;
                serialByteDataType.set_value_type( SerializeValueType::Double_TYPE );
                serialByteDataType.set_data( serialize.SerializeAsString());
                // 插入
                serialStringList.mutable_datas()->insert(
                        google::protobuf::MapPair<std::string, SerialByteDataType>( v.first, serialByteDataType ));

                break;
            }

            case ValueType_STRING:
            {
                // 序列化
                // 原数据
                SerializeString serialize;
                ValueDataStringType *valueData = (ValueDataStringType *) v.second->getDataPort().get();
                serialize.set_data( valueData->data );
                // 中间类型
                SerialByteDataType serialByteDataType;
                serialByteDataType.set_value_type( SerializeValueType::String_TYPE );
                serialByteDataType.set_data( serialize.SerializeAsString());
                // 插入
                serialStringList.mutable_datas()->insert(
                        google::protobuf::MapPair<std::string, SerialByteDataType>( v.first, serialByteDataType ));

                break;
            }

            case ValueType_BOOL:{
                // 序列化
                // 原数据
                SerializeBool serialize;
                ValueDataBoolType *valueData = (ValueDataBoolType *) v.second->getDataPort().get();
                serialize.set_data( valueData->data );
                // 中间类型
                SerialByteDataType serialByteDataType;
                serialByteDataType.set_value_type( SerializeValueType::Bool_TYPE );
                serialByteDataType.set_data( serialize.SerializeAsString());
                // 插入
                serialStringList.mutable_datas()->insert(
                        google::protobuf::MapPair<std::string, SerialByteDataType>( v.first, serialByteDataType ));

                break;
            }

            default:
            {
                std::cout << "pass " << std::endl;
                break;
            }
        }
    }

    //保存到文件
    std::ofstream outfile;
    outfile.open( m_filename, std::ios::out | std::ios::trunc );
    outfile << serialStringList.SerializeAsString();
    outfile.close();
}


template<class T, typename F>
bool FileSerialInsertMap(F f, std::map<std::string, KeyValueDataTypePort> &map)
{
    T serialize;
    serialize.ParseFromString( f.second.data());
    auto isok = map.insert( std::pair<std::string, KeyValueDataTypePort>( f.first, std::shared_ptr<KeyValueDataType>(
            new KeyValueDataType( serialize.data()))));
    // TODO 是否替换缓存
    return isok.second;

}

void KeyValueFileService::load()
{
    std::ifstream ifstream( m_filename );
    std::string getSerializeBuffer((std::istreambuf_iterator<char>( ifstream )),
                                   std::istreambuf_iterator<char>());
    ifstream.close();

    // 反序列化
    SerialStringList serialStringList;

    if (!serialStringList.ParseFromString( getSerializeBuffer ))
    {
        // 失败
        std::cout << " load file " << m_filename << " fail ! " << std::endl;
        return;
    }

    for (auto f : serialStringList.datas())
    {
        // 储存
        switch (f.second.value_type())
        {
            case SerializeValueType::INT64_TYPE:
            {
                // TODO 是否替换缓存
                if (FileSerialInsertMap<SerializeInt64>( f, cacheKeyValueMap ))
                {
                    //成功
                } else
                {
                    // 已存在 这里不替换
                }
                break;
            }
                // int 32
            case SerializeValueType::INT32_TYPE:
            {
                // TODO 是否替换缓存
                if (FileSerialInsertMap<SerializeInt32>( f, cacheKeyValueMap ))
                {
                    //成功
                } else
                {
                    // 已存在 这里不替换
                }
                break;
            }


                // float
            case SerializeValueType::Float_TYPE:
            {
                // TODO 是否替换缓存
                if (FileSerialInsertMap<SerializeFloat>( f, cacheKeyValueMap ))
                {
                    //成功
                } else
                {
                    // 已存在 这里不替换
                }
                break;
            }

            case SerializeValueType::Double_TYPE:
            {
                // TODO 是否替换缓存
                if (FileSerialInsertMap<SerializeDouble>( f, cacheKeyValueMap ))
                {
                    //成功
                } else
                {
                    // 已存在 这里不替换
                }
                break;
            }

            case SerializeValueType::String_TYPE:
            {
                // TODO 是否替换缓存
                if (FileSerialInsertMap<SerializeString>( f, cacheKeyValueMap ))
                {
                    //成功
                } else
                {
                    // 已存在 这里不替换
                }
                break;
            }


            case SerializeValueType::Bool_TYPE:
            {
                // TODO 是否替换缓存
                if (FileSerialInsertMap<SerializeBool>( f, cacheKeyValueMap ))
                {
                    //成功
                } else
                {
                    // 已存在 这里不替换
                }
                break;
            }
        }

    }


}

void KeyValueFileService::DeciptherFunction(std::string &inString, std::string &outString)
{

}

void KeyValueFileService::EnciptherFunction(std::string &inString, std::string &outString)
{

}

void KeyValueFileService::EnCodeFunction(KeyValueDataTypePort inData, std::string &outString)
{

}

void KeyValueFileService::DeCodeFunction(std::string &inString, KeyValueDataTypePort inData)
{

}

KeyValueFileService::~KeyValueFileService()
{
    for (auto v : cacheKeyValueMap)
    {
        v.second.reset();
    }
    cacheKeyValueMap.clear();
}

#endif